#include "web/web_server.h"
#include "web/web_utils.h"
#include "web/web_status.h"
#include "web/web_status_ui.h"
#include <atomic>
#include <vector>
#include <string>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <functional>
#include <sstream>
#include <netinet/in.h>
#include <unistd.h>

struct WebMJPEGServer::Impl {
    int port;
    std::atomic<bool> running{false};
    std::thread server_thread;
    std::function<std::vector<uint8_t>()> frame_provider;
    std::mutex frame_mutex;
    std::condition_variable frame_cv;
};

WebMJPEGServer::WebMJPEGServer(int port) : impl_(new Impl{port}) {}
WebMJPEGServer::~WebMJPEGServer() { stop(); delete impl_; }

void WebMJPEGServer::setFrameProvider(std::function<std::vector<uint8_t>()> provider) {
    impl_->frame_provider = std::move(provider);
}

void WebMJPEGServer::start() {
    if (impl_->running) return;
    impl_->running = true;
    impl_->server_thread = std::thread([this](){
        int server_fd = socket(AF_INET, SOCK_STREAM, 0);
        int opt = 1;
        setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
        sockaddr_in addr{};
        addr.sin_family = AF_INET;
        addr.sin_addr.s_addr = INADDR_ANY;
        addr.sin_port = htons(impl_->port);
        bind(server_fd, (struct sockaddr*)&addr, sizeof(addr));
        listen(server_fd, 4);
        while (impl_->running) {
            int client_fd = accept(server_fd, nullptr, nullptr);
            if (client_fd < 0) continue;
            char req_buf[1024] = {0};
            recv(client_fd, req_buf, sizeof(req_buf)-1, MSG_PEEK);
            std::string req_str(req_buf);
            if (req_str.find("GET /stats_time") == 0 || req_str.find("GET /stats_time ") == 0) {
                extern WebStatus g_web_status;
                std::string html = "更新时间：" + g_web_status.last_update;
                std::ostringstream oss;
                oss << "HTTP/1.0 200 OK\r\nContent-Type: text/html; charset=utf-8\r\nContent-Length: " << html.size() << "\r\n\r\n";
                send(client_fd, oss.str().c_str(), oss.str().size(), 0);
                send(client_fd, html.c_str(), html.size(), 0);
                close(client_fd);
            } else if (req_str.find("GET /stats") == 0 || req_str.find("GET /stats ") == 0) {
                // 只返回统计HTML片段
                extern WebStatus g_web_status;
                extern std::string render_status_html(const WebStatus&);
                std::string html = render_status_html(g_web_status);
                std::ostringstream oss;
                oss << "HTTP/1.0 200 OK\r\nContent-Type: text/html; charset=utf-8\r\nContent-Length: " << html.size() << "\r\n\r\n";
                send(client_fd, oss.str().c_str(), oss.str().size(), 0);
                send(client_fd, html.c_str(), html.size(), 0);
                close(client_fd);
            } else if (req_str.find("GET /mjpeg") == 0 || req_str.find("GET /mjpeg ") == 0) {
                // MJPEG流接口
                std::thread([this, client_fd]() {
                    std::string header =
                        "HTTP/1.0 200 OK\r\n"
                        "Server: MJPEGStreamer/1.0\r\n"
                        "Content-Type: multipart/x-mixed-replace; boundary=frame\r\n"
                        "Cache-Control: no-cache\r\n"
                        "Pragma: no-cache\r\n\r\n";
                    send(client_fd, header.c_str(), header.size(), 0);
                    while (impl_->running) {
                        if (!impl_->frame_provider) { usleep(10000); continue; }
                        auto jpeg = impl_->frame_provider();
                        if (jpeg.empty()) { usleep(10000); continue; }
                        std::ostringstream oss;
                        oss << "--frame\r\nContent-Type: image/jpeg\r\nContent-Length: " << jpeg.size() << "\r\n\r\n";
                        send(client_fd, oss.str().c_str(), oss.str().size(), 0);
                        send(client_fd, reinterpret_cast<char*>(jpeg.data()), jpeg.size(), 0);
                        send(client_fd, "\r\n", 2, 0);
                        usleep(40000); // ~25fps
                    }
                    close(client_fd);
                }).detach();
            } else if (req_str.find("GET / ") == 0 || req_str.find("GET /HTTP") == 0) {
                // 只处理根路径为主页面，避免 /stats /mjpeg 被误判
                extern WebStatus g_web_status;
                extern std::string render_status_html(const WebStatus&);
                std::string html = R"(
<!DOCTYPE html>
<html>
<head>
  <title>YOLOv11 实时检测</title>
  <meta charset='utf-8'>
  <meta name='viewport' content='width=device-width,initial-scale=1'>
  <style>
    body { background:#181c24; color:#f3f6fa; margin:0; font-family:'Segoe UI',Arial,sans-serif; }
    .title-bar {
      width:50vw; min-width:320px; margin:36px auto 18px auto;
      font-size:2.8em; font-weight:700; text-align:center; letter-spacing:2px;
      background: linear-gradient(90deg,#2d3a4a 0%,#1e90ff 100%);
      color:#fff; border-radius:18px; box-shadow:0 4px 24px #0008;
      padding:18px 0; user-select:none;
    }
    .stats-row {
      display:flex; flex-direction:row; justify-content:center; gap:32px;
      margin-bottom:36px;
    }
    .stat-card {
      background:#232b39; border-radius:16px; box-shadow:0 2px 12px #0006;
      min-width:160px; min-height:90px; padding:24px 28px; display:flex; flex-direction:column; align-items:center;
      transition:box-shadow .2s;
      font-size:1.25em;
    }
    .stat-label { color:#8cb3f4; font-size:1em; margin-bottom:8px; }
    .stat-value { font-size:2.1em; font-weight:600; color:#fff; letter-spacing:1px; }
    .video-area {
      display:flex; flex-direction:column; align-items:center; margin-top:18px;
    }
    .video-frame {
      max-width:70vw; min-width:320px; border-radius:14px; box-shadow:0 0 16px #000b;
      background:#111; margin-bottom:12px;
    }
    .video-label { color:#aaa; font-size:1em; margin-bottom:24px; }
    @media (max-width:900px) {
      .title-bar { width:96vw; font-size:2em; }
      .stats-row { flex-direction:column; align-items:center; gap:16px; }
      .stat-card { min-width:180px; width:90vw; }
      .video-frame { max-width:98vw; }
    }
  </style>
</head>
<body>
  <div class='title-bar'>YOLOv11 实时检测系统</div>
  <div id='stats_area'>
    )" + render_status_html(g_web_status) + R"(
  </div>
  <div class='video-area'>
    <img class='video-frame' src='/mjpeg'>
    <div class='video-label'>实时检测视频</div>
  </div>
  <div id='update_time' style='text-align:center; color:#8cb3f4; font-size:14px; margin:10px 0 30px 0;'>更新时间：)" + g_web_status.last_update + R"(</div>
  <script>
    function updateStats() {
      fetch('/stats').then(r => r.text()).then(html => {
        document.getElementById('stats_area').innerHTML = html;
      });
      fetch('/stats').then(r => r.text()).then(_ => {
        fetch('/stats_time').then(r2 => r2.text()).then(timeHtml => {
          document.getElementById('update_time').innerHTML = timeHtml;
        });
      });
    }
    setInterval(updateStats, 2000);
    updateStats();
  </script>
</body>
</html>
)";
                std::ostringstream oss;
                oss << "HTTP/1.0 200 OK\r\nContent-Type: text/html; charset=utf-8\r\nContent-Length: " << html.size() << "\r\n\r\n";
                send(client_fd, oss.str().c_str(), oss.str().size(), 0);
                send(client_fd, html.c_str(), html.size(), 0);
                close(client_fd);
            }
        }
        close(server_fd);
    });
}

void WebMJPEGServer::stop() {
    if (!impl_->running) return;
    impl_->running = false;
    if (impl_->server_thread.joinable()) impl_->server_thread.join();
}

bool WebMJPEGServer::isRunning() const { return impl_->running; }
